package com.inno.auth.controller.controller;

import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.Assert;
import com.google.common.base.Preconditions;
import com.inno.auth.common.annotiation.Hidden;
import com.inno.auth.common.annotiation.Log;
import com.inno.auth.common.context.LoginUserContext;
import com.inno.auth.common.entity.CommonReturnType;
import com.inno.auth.common.entity.PageResult;
import com.inno.auth.common.enums.IsDeletedFlagEnum;
import com.inno.auth.common.error.AuthException;
import com.inno.auth.common.utils.DesensitizedUtil;
import com.inno.auth.controller.convert.AuthUserDTOConverter;
import com.inno.auth.controller.dto.EnumDTO;
import com.inno.auth.controller.dto.PlannerUsersDTO;
import com.inno.auth.domain.entity.PlannerUsersBO;
import com.inno.auth.domain.service.UsersDomainService;
import com.inno.auth.entity.AuthUserDTO;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

/**
 * @author sean
 */
@Slf4j
@RestController
@RequestMapping("/auth/user")
public class AuthUserController {
    @Resource
    private UsersDomainService usersDomainService;

    @PostMapping("/getUserInfo")
    public CommonReturnType<AuthUserDTO> getUserInfo(@RequestBody(required = false) AuthUserDTO authUserDTO) {
        if (authUserDTO == null){
            AuthUserDTO dto = new AuthUserDTO();
            PlannerUsersBO plannerUsersBO = AuthUserDTOConverter.INSTANCE.convertAuthUserDTOToBO(dto);
            Object loginId = StpUtil.getLoginId();
            plannerUsersBO.setId(Long.valueOf(loginId.toString()));
            PlannerUsersBO boResult = usersDomainService.getUserInfo(plannerUsersBO);
            AuthUserDTO authUserResult = AuthUserDTOConverter.INSTANCE.convertBOToAuthUserDTO(boResult);
            return CommonReturnType.success(authUserResult);
        }
        PlannerUsersBO bo = AuthUserDTOConverter.INSTANCE.convertAuthUserDTOToBO(authUserDTO);
        PlannerUsersBO boResult = usersDomainService.getUserInfo(bo);

        AuthUserDTO authUserResult = AuthUserDTOConverter.INSTANCE.convertBOToAuthUserDTO(boResult);

        return CommonReturnType.success(authUserResult);
    }

    @PostMapping("/getUserInfoByIdList")
    @Hidden
    public CommonReturnType<List<AuthUserDTO>> getUserInfoByIdList(@RequestBody List<Long> idList, HttpServletRequest request) {
        log.info("header:{}",request.getHeader("source"));
        List<PlannerUsersBO> boList = usersDomainService.getUserInfoByIdList(idList);
        List<AuthUserDTO> dtoList = AuthUserDTOConverter.INSTANCE.convertBOListToAuthUserDTOList(boList);
        return CommonReturnType.success(dtoList);
    }

    @PostMapping("/queryPage")
    public CommonReturnType<PageResult<PlannerUsersDTO>> queryPage(@RequestBody PlannerUsersDTO plannerUsersDTO){
        Preconditions.checkNotNull(plannerUsersDTO.getPage(),"分页参数不能为空");
        Preconditions.checkNotNull(plannerUsersDTO.getPageSize(),"分页参数不能为空");
        PlannerUsersBO plannerUsersBO = convertDTOToBO(plannerUsersDTO);
        PageResult<PlannerUsersBO> boResult = this.usersDomainService.queryPage(plannerUsersBO);

        return CommonReturnType.success(PageResult.of(convertBOListToDTOList(boResult.getList()), boResult.getTotal()));
    }

    /**
     * 检查登录状态
     */
    @PostMapping("/checkLogin")
    public CommonReturnType<Boolean> checkLogin(@RequestBody AuthUserDTO authUserDTO){
        return CommonReturnType.success(StpUtil.isLogin(authUserDTO.getId()));
    }

    /**
     * 获取用户信息
     */
    @PostMapping("/info")
    public CommonReturnType<PlannerUsersDTO> info(@RequestBody PlannerUsersDTO plannerUsersDTO){
        if (plannerUsersDTO.getId() == null){
            plannerUsersDTO.setId(LoginUserContext.getUserId());
            log.info("用户id为空，使用当前登录用户id：{}", plannerUsersDTO.getId());
        }
        PlannerUsersBO plannerUsersBO = convertDTOToBO(plannerUsersDTO);
        PlannerUsersBO userInfo = usersDomainService.getUserInfo(plannerUsersBO);
        log.info("domain返回的获取用户信息：{}", userInfo);
        PlannerUsersDTO dtoResult = convertBOToDTO(userInfo);
        dtoResult.setPassword(DesensitizedUtil.password(dtoResult.getPassword())); ;
        dtoResult.setMobile(DesensitizedUtil.mobile(dtoResult.getMobile()));
        dtoResult.setEmail(DesensitizedUtil.email(dtoResult.getEmail()));
        log.info("controller返回的获取用户信息：{}", dtoResult);
        return CommonReturnType.success(dtoResult);
    }
    @PostMapping("/update")
    public CommonReturnType<Void> update(@RequestBody PlannerUsersDTO plannerUsersDTO){
        if (plannerUsersDTO.getId() == null){
            throw new AuthException("id不能为空");
        }
        PlannerUsersBO bo = convertDTOToBO(plannerUsersDTO);
        if (Objects.isNull(plannerUsersDTO.getId())){
            bo.setId(LoginUserContext.getUserId());
        }
        usersDomainService.update(bo);
        if (StringUtils.isNotBlank(plannerUsersDTO.getPassword())){
            StpUtil.logout(plannerUsersDTO.getId());
        }
        return CommonReturnType.success();
    }

    @PostMapping("/cancelAccount")
    @Log(operationType = "cancelAccount")
    public CommonReturnType<Void> cancelAccount(@RequestBody PlannerUsersDTO plannerUsersDTO){
        if (plannerUsersDTO.getId() == null){
            throw new AuthException("id不能为空");
        }
        PlannerUsersBO bo = convertDTOToBO(plannerUsersDTO);

        Long currentUser = LoginUserContext.getUserId();
        if (!currentUser.equals(bo.getId())){
            throw new AuthException("非法操作");
        }
        bo.setId(currentUser);
        usersDomainService.cancelAccount(bo);
        StpUtil.logout(currentUser.toString());
        return CommonReturnType.success();
    }
    @GetMapping("/status")
    public CommonReturnType<List<EnumDTO>> statusList (){
        List<EnumDTO> result = new ArrayList<>();
        for (IsDeletedFlagEnum value : IsDeletedFlagEnum.values()) {
            EnumDTO enumDTO = new EnumDTO();
            enumDTO.setCode(value.getCode().toString());
            enumDTO.setDesc(value.getDesc());
            result.add(enumDTO);
        }
        return CommonReturnType.success(result);
    }
    @PostMapping("/todayRegisterCount")
    public CommonReturnType<Long> todayRegisterCount(){
        return CommonReturnType.success(usersDomainService.todayRegisterCount());
    }
    @PostMapping("/totalRegisterCount")
    public CommonReturnType<Long> totalRegisterCount(){
        return CommonReturnType.success(usersDomainService.totalRegisterCount());
    }

    @PostMapping("/send-bind-sms")
    public CommonReturnType<Void> sendBindSms(@RequestBody PlannerUsersDTO usersDTO) {
        Preconditions.checkArgument(!StringUtils.isBlank(usersDTO.getMobile()),"手机号不能为空");
        this.usersDomainService.sendBindSms(convertDTOToBO(usersDTO));
        return CommonReturnType.success();
    }

    @PostMapping("/bindMobile")
    @Log(operationType = "bindMobile")
    public CommonReturnType<Void> bindMobile(@RequestBody PlannerUsersDTO usersDTO){
        Assert.notBlank(usersDTO.getMobile(),()->new AuthException("手机号不能为空"));
        Assert.notBlank(usersDTO.getCode(),()->new AuthException("验证码不能为空"));
        Long userId = LoginUserContext.getUserId();
        usersDTO.setId(userId);
        this.usersDomainService.bindMobile(convertDTOToBO(usersDTO));
        return CommonReturnType.success();
    }



    private PlannerUsersBO convertDTOToBO(PlannerUsersDTO usersDTO) {
        PlannerUsersBO plannerUsersBO = new PlannerUsersBO();
        BeanUtil.copyProperties(usersDTO, plannerUsersBO);
        return plannerUsersBO;
    }

    private PlannerUsersDTO convertBOToDTO(PlannerUsersBO boResult) {
        PlannerUsersDTO plannerUsersDTO = new PlannerUsersDTO();
        BeanUtil.copyProperties(boResult, plannerUsersDTO);
        return plannerUsersDTO;
    }

    private List<PlannerUsersDTO> convertBOListToDTOList(List<PlannerUsersBO> boList){
        List<PlannerUsersDTO> result = new ArrayList<>();
        for (PlannerUsersBO plannerUsersDTO : boList) {
            result.add(convertBOToDTO(plannerUsersDTO));
        }
        return result;
    }
}
